import type { App, DirectiveBinding, ObjectDirective } from "vue"

interface ElTableInfiniteScrollHTMLElement extends HTMLElement {
  _onScroll?: EventListener
}

// 将 DISTANCE 提取为常量，使其在所有钩子函数中可用
const DISTANCE = 100 // 距离底部多少像素时触发加载

export const elTableInfiniteScroll: ObjectDirective = {
  mounted(el: ElTableInfiniteScrollHTMLElement, binding: DirectiveBinding) {
    const container = el.querySelector(".el-scrollbar__wrap") as HTMLElement

    if (!container) {
      console.warn("[el-table-infinite-scroll] 找不到 .el-scrollbar__wrap 元素")
      return
    }

    const loadMore = binding.value

    if (typeof loadMore !== "function") {
      console.warn("[el-table-infinite-scroll] v-el-table-infinite-scroll 的值必须是一个函数")
      return
    }

    // 保存事件处理函数的引用，以便在 unmounted 时移除
    const onScroll = function (this: HTMLElement) {
      const scrollDistance = this.scrollHeight - this.scrollTop - this.clientHeight
      if (scrollDistance <= DISTANCE) {
        loadMore()
      }
    }

    // 保存引用以便清理
    el._onScroll = onScroll

    container.addEventListener("scroll", onScroll)

    // 初始检查，如果内容不足以滚动，也应该触发加载
    if (container.scrollHeight <= container.clientHeight) {
      loadMore()
    }
  },

  updated(el: ElTableInfiniteScrollHTMLElement, binding: DirectiveBinding) {
    // 如果绑定的函数发生变化，更新事件处理程序
    if (binding.value !== binding.oldValue) {
      const container = el.querySelector(".el-scrollbar__wrap") as HTMLElement

      if (!container || !el._onScroll) return

      // 移除旧的事件监听器
      container.removeEventListener("scroll", el._onScroll)

      // 添加新的事件监听器
      const loadMore = binding.value

      const onScroll = function (this: HTMLElement) {
        const scrollDistance = this.scrollHeight - this.scrollTop - this.clientHeight
        if (scrollDistance <= DISTANCE) {
          loadMore()
        }
      }

      el._onScroll = onScroll
      container.addEventListener("scroll", onScroll)
    }
  },

  unmounted(el: ElTableInfiniteScrollHTMLElement) {
    const container = el.querySelector(".el-scrollbar__wrap") as HTMLElement
    if (container && el._onScroll) {
      container.removeEventListener("scroll", el._onScroll)
      delete el._onScroll
    }
  }
}

export default {
  install(app: App) {
    app.directive("el-table-infinite-scroll", elTableInfiniteScroll)
  }
}
